/* 
* Copyright (C) 2005, 2006 Liu Di <liudidi@gmail.com> 
*
* Copyright (C) 2007 Wei Lian <lianwei3@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "sopfork.h"
#include "record.h"
#include "header.h"
#include "config.h"
#include "channel.h"
#include "timing.h"
#include "tabwidget.h"
#include "mainwindow.h"
#include "menubar.h"
#include "utils.h"
#include "mystatusbar.h"


Record::Record (QWidget * parent, const char *name):
MyVBox (parent, name),
tabwidget (static_cast < TabWidget * >(parent))
{
   ///set page type 
   pagetype = "record";

   recordfp = new QFile ();
   snrecord = 0;

   launchtimer = new QTimer (this);
   connect (launchtimer, SIGNAL (timeout ()), this, SLOT (launchRecord ()));

   quittimer = new QTimer (this);
   connect (quittimer, SIGNAL (timeout ()), this, SLOT (quitRecord ()));

   ///row
   QHBox *hbox = new QHBox (this);
   ///status bar
   statusbar = new QStatusBar (hbox);
   statusbar->setSizeGripEnabled (false);
   statusbar->hide ();
   ///input for timing
   timing = new Timing (hbox);
   ///button record
   buttonrecord = new QToolButton (hbox);
   buttonrecord->setTextLabel (tr ("Record"));
   buttonrecord->setAutoRaise (true);
   buttonrecord->setUsesTextLabel (true);
   buttonrecord->setToggleButton (TRUE);
//    buttonrecord->setMaximumSize(buttonrecord->sizeHint());
   //signal
   connect (buttonrecord, SIGNAL (toggled (bool)), this,
	    SLOT (onButtonRecordToggled (bool)));
   ///button delete
   QToolButton *but = new QToolButton (hbox);
   but->setTextLabel (tr ("x"));
   but->setAutoRaise (true);
   but->setUsesTextLabel (true);
   but->setMaximumSize (but->sizeHint ());
   connect (but, SIGNAL (clicked ()), this, SLOT (removeTab ()));

   ///initialize flagMenu
   flagMenu = false;
}

Record::~Record ()
{
   tabwidget->detachSop (&sopfork, this);
   ///
   if (snrecord) {
      recordfp->close ();
      ::close (snrecord->socket ());
      delete snrecord;
      snrecord = 0;
   }
   delete recordfp;
}


void
Record::streamReady (int fd)
{
   int ret;
   char buff[1024];
   ret =::read (fd, buff, sizeof (buff));
   if (ret <= 0) {
      if (ret < 0)
	 perror ("record socketnotifier");

      recordfp->close ();
      ::close (fd);
      delete snrecord;
      snrecord = 0;
      buttonrecord->setPaletteForegroundColor (Qt::black);

      /////restart record
      launchtimer->start (2000, true);

      return;
   }
   ::write (recordfp->handle (), buff, ret);
}


void
Record::launchRecord ()
{
   ///show message on statusbar
   static_cast < MainWindow * >(qApp->mainWidget ())
      ->statusbar->showMessage (tr ("Connecting..."));
   ////launch Sop
   if (!sopfork) {
      if (tabwidget->attachSop (&sopfork, this, channelurl,
				channelname) == TRUE) {
      }
      else
	 fprintf (stderr, "failed to launch sp-sc!\n");
   }
   else if (sopfork->channelurl != channelurl) {
      tabwidget->detachSop (&sopfork, this);
      if (tabwidget->attachSop (&sopfork, this, channelurl,
				channelname) == TRUE) {
      }
      else
	 fprintf (stderr, "failed to launch sp-sc!\n");
   }
   ////handle stream
   int sockfd = connect_to_server ("127.0.0.1",
				   atoi (sopfork->outport));
   if (sockfd < 0) {
      ///restart
      launchtimer->start (2000, true);
      return;
   }
   ::write (sockfd, "1",::strlen ("1") + 1);
   ///parse header
   char buf[19];
   if (::recv (sockfd, buf, sizeof (buf), 0) != sizeof (buf)) {
      fprintf (stderr, "err while parsing head\n");
      ::close (sockfd);
      buttonrecord->setOn (false);
      return;
   }
   ///testing data availibility
   int nread;
   ::ioctl (sockfd, FIONREAD, &nread);
   if (nread <= 0) {
      ::close (sockfd);
      ////
      if (nread < 0)
	 perror ("ioctl get nread of socket");
      ///restart
      launchtimer->start (2000, true);
      return;
   }
   ////data availible
   QString data_path = static_cast < MainWindow * >(qApp->mainWidget ())
      ->vboxconfig->editrecorddir->text ();
   QDir dir (data_path);
   if (!dir.exists ())
      if (!dir.mkdir (data_path)) {
	 perror ("failed to create record path");
	 ::close (sockfd);
	 buttonrecord->setOn (false);
	 return;
      }
   data_path += sopfork->channelname.replace (QRegExp ("\\/+"), "#");	///eliminate harmful character
   data_path += QDateTime::currentDateTime ().toString ();
   data_path += ".asf";
   recordfp->setName (data_path);
   if (!recordfp->open (IO_WriteOnly)) {
      perror ("record file name is invalid");
      ::close (sockfd);
      buttonrecord->setOn (false);
      return;
   }
   if (snrecord) {
      fprintf (stderr, "QSocketNotifier exist!\n");
      return;
   }
   snrecord = new QSocketNotifier (sockfd, QSocketNotifier::Read, this);
   connect (snrecord, SIGNAL (activated (int)), SLOT (streamReady (int)));
   buttonrecord->setPaletteForegroundColor (Qt::red);
}

void
Record::quitRecord ()
{
   buttonrecord->setOn (false);
}

void
Record::onButtonRecordToggled (bool t)
{
   if (t) {
      if (!flagMenu) {
	 ///if not launched from bookmark or history
	 QListViewItem *item =
	    static_cast < MainWindow * >(qApp->mainWidget ())
	    ->channel->currentItem ();
	 if (!item || item->depth () != 1) {
	    buttonrecord->setOn (false);
	    return;
	 }
	 ///get channel name and url
	 channelname = item->text (NAME_COLUMN);
	 channelurl = item->text (URL_COLUMN);
	 channeltype = item->text (STREAM_COLUMN);
      }
      ///get time for current, from and to
      int current =
	 QTime::currentTime ().hour () * 60 * 60 +
	 QTime::currentTime ().minute () * 60 +
	 QTime::currentTime ().second ();
      int from =
	 timing->fromHour->text ().toInt () * 60 * 60 +
	 timing->fromMinute->text ().toInt () * 60;
      int to =
	 timing->toHour->text ().toInt () * 60 * 60 +
	 timing->toMinute->text ().toInt () * 60;
      ///calculate delay time for record start and stop
      int delaystart, delaystop;
      QString fromdaytime, todaytime;
      if (timing->fromHour->text ().isEmpty ()
	  && timing->toHour->text ().isEmpty ()) {
	 delaystart = 0;
	 delaystop = -1;
	 ///
	 fromdaytime = tr ("today/now");
	 todaytime = tr ("inf");
      }
      else if (timing->fromHour->text ().isEmpty ()) {
	 delaystart = 0;
	 delaystop =
	    to - current >= 0 ? to - current : to - current + 24 * 60 * 60;
	 ///
	 fromdaytime = tr ("today/now");
	 todaytime = to - current >= 0 ? tr ("today/") : tr ("tomor/");
	 todaytime +=
	    timing->toHour->text () + ":" + timing->toMinute->text ();
	 ///
      }
      else if (timing->toHour->text ().isEmpty ()) {
	 delaystart =
	    from - current >=
	    0 ? from - current : from - current + 24 * 60 * 60;
	 delaystop = -1;
	 ///
	 fromdaytime = from - current >= 0 ? tr ("today/") : tr ("tomor/");
	 fromdaytime +=
	    timing->fromHour->text () + ":" + timing->fromMinute->text ();
	 todaytime = tr ("inf");
	 ///
      }
      else {
	 delaystart =
	    from - current >=
	    0 ? from - current : from - current + 24 * 60 * 60;
	 delaystop = to - from >= 0 ? to - from : to - from + 24 * 60 * 60;
	 delaystop = delaystop + delaystart;
	 ///
	 fromdaytime = from - current >= 0 ? tr ("today/") : tr ("tomor/");
	 fromdaytime +=
	    timing->fromHour->text () + ":" + timing->fromMinute->text ();
	 switch ((from - current < 0) + (to - from < 0)) {
	 case 0:
	    todaytime = tr ("today/");
	    break;
	 case 1:
	    todaytime = tr ("tomor/");
	    break;
	 case 2:
	    todaytime = tr ("aftto/");
	 }
	 todaytime +=
	    timing->toHour->text () + ":" + timing->toMinute->text ();
      }
      ///start timer for starting record
      launchtimer->start (delaystart * 1000, true);
      ///start timer for stoping record
      if (delaystop >= 0) {
	 quittimer->start (delaystop * 1000, true);
      }
      ///change interface
      statusbar->message (fromdaytime + "-" + todaytime + "|" + channelname);
      statusbar->show ();
      timing->hide ();
      ///log
      printf ("record start after %d hour and %d minute %d second\n",
	      delaystart / 3600, delaystart / 60 % 60, delaystart % 60);
      if (delaystop >= 0)
	 printf ("   and stop after %d hour and %d minute %d second\n",
		 delaystop / 3600, delaystop / 60 % 60, delaystop % 60);
      ///assign channel name to tab label
      tabwidget->setTabLabel (this, reduceLabelLength (channelname));
      ///add to history
      static_cast < MainWindow * >(qApp->mainWidget ())
	 ->menubar->addToPopupMenu (static_cast < MainWindow * >
				    (qApp->mainWidget ())->
				    menubar->history,
				    channelurl, channelname, channeltype);
   }
   else				///function setOn(false) will trigger the following code
   {
      ///close file, socket and socketnotifier
      if (snrecord) {
	 recordfp->close ();
	 ::close (snrecord->socket ());
	 delete snrecord;
	 snrecord = 0;
      }
      ///reset button color
      buttonrecord->setPaletteForegroundColor (Qt::black);
      ///stop timer
      launchtimer->stop ();
      quittimer->stop ();
      ///change interface
      statusbar->hide ();
      timing->show ();
      ///kill sop
      tabwidget->detachSop (&sopfork, this);
      ///assign channel name to tab label
      tabwidget->setTabLabel (this, tr ("record"));
      ///clean statusbar
      static_cast < MainWindow * >(qApp->mainWidget ())
	 ->statusbar->showMessage ("");
   }

}

void
Record::removeTab ()
{
   if (tabwidget->count () == 1)
      return;
   tabwidget->removePage (this);
   delete this;
}
